package com.zyx.concurrentdemo.mytest.c04;

import com.zyx.concurrentdemo.c02basic.util.Sleeper;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author zyx
 * @since 2021/10/16 19:25
 * desc: 基于 ReentrantLock的 await 和 signal 进行顺序打印
 */
public class OrderingPrintDemo03 {
    public static void main(String[] args) {
        AwaitAndSignal awaitAndSignal = new AwaitAndSignal(5);
        Condition c1 = awaitAndSignal.newCondition();
        Condition c2 = awaitAndSignal.newCondition();
        Condition c3 = awaitAndSignal.newCondition();

        Thread t1 = new Thread(() -> awaitAndSignal.run("a", c1, c2), "t1");
        Thread t2 = new Thread(() -> awaitAndSignal.run("b", c2, c3), "t2");
        Thread t3 = new Thread(() -> awaitAndSignal.run("c", c3, c1), "t3");

        t1.start();
        t2.start();
        t3.start();

        Sleeper.sleep(1);

        awaitAndSignal.lock();
        try {
            c1.signalAll();
        } finally {
            awaitAndSignal.unlock();
        }
    }
}

class AwaitAndSignal extends ReentrantLock {
    /**
     * 循环次数
     */
    private final int loopNumber;

    public AwaitAndSignal(int loopNumber) {
        this.loopNumber = loopNumber;
    }

    public void run(String msg, Condition current, Condition next) {
        for (int i = 0; i < loopNumber; i++) {
            lock();
            try {
                // 当前变量条件进行等待
                current.await();
                System.out.print(msg);
                // 唤醒下一个变量条件
                next.signal();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                unlock();
            }

        }
    }

}
